/*
 * @Description: axios封装
 * @Autor: 人生
 * @Date: 2020-09-27 14:00:28
 * @,@LastEditors: ,: 人生
 */
import axios from "axios";
import store from "@/store";
import storage from "store";
import router from "@/router";
import { ACCESS_TOKEN } from "@/store/mutation-types";
import { message, notification } from "ant-design-vue";
import { Loading } from "@/components/pageLoading";
// import { Message, Loading } from 'element-ui'
import { v4 as uuidv4 } from "uuid";

// 将axios 二次封装
// 每个实例的拦截器和其他人无关 ，如果使用全局的实例 那么给每次请求单独配置拦截器就做不到
let flag = false;
class HttpRequest {
  constructor() {
    // 可以增加实例属性 后台接口的路径  开发模式和生产模式不一样 在config里新建index.js进行配置
    this.baseURL = process.env.VUE_APP_API_BASE_URL; // 默认地址
    this.timeout = 1000 * 100; // 100s后请求超时
    this.loadingInstance = null;
  }
  // 创建单独的拦截器
  setInterceptors(instance, options) {
    let timer = null;
    instance.interceptors.request.use(config => {
      // 一般增加一些token属性等
      const token = storage.get(ACCESS_TOKEN);
      // 如果 token 存在
      // 让每个请求携带自定义 token 请根据实际情况自行修改
      if (token) {
        config.headers[ACCESS_TOKEN] = token;
      }
      // 唯一请求id
      config.headers["requestId"] = uuidv4();
      // 每次请求时间
      config.headers["requestTime"] = Date.parse(new Date())
        .toString()
        .substr(0, 10);
      const { loadingEl, title } = config;
      const cancel = config.cancel || {};
      const _self = cancel._self;
      if (loadingEl) {
        // 增加loading,并进行600ms延时
        timer = setTimeout(() => {
          this.loadingInstance = Loading.service({
            target: loadingEl,
            title
          });
        }, 600);
      }
      if (_self) {
        // 取消请求
        const CancelToken = axios.CancelToken;
        const source = CancelToken.source();
        config.cancelToken = source.token;
        _self.$data.cancelRequest.push(source);
      }
      return config;
    });
    instance.interceptors.response.use(
      res => {
        //取消延时loading的加载
        clearTimeout(timer);
        // 关闭loading
        this.loadingInstance && this.loadingInstance.close();
        // 服务返回的结果都会放到data中
        const { data } = res;
        //oss上传没有返回data内容
        if (!data) return Promise.resolve(res.data);
        if (res.status === 200) {
          const reCode = data.reCode;
          switch (reCode) {
            case 0:
              return Promise.resolve(res.data);
            case -1994: //token无效
            case -1004: //账号冻结
            case -1007: //用户不存在
            case -9999: //系统异常
              if (!flag) {
                message.error(data.reMsg);
                flag = true;
                setTimeout(() => {
                  flag = false;
                }, 3000);
              }
              storage.remove(ACCESS_TOKEN);
              // window.location.href = '/user/login'
              router.push({
                path: "/user/login"
              });
              return Promise.reject(res.data);
            default:
              // 失败
              message.error(data.reMsg);
              return Promise.reject(res.data);
          }
        } else {
          const msg = res.reMsg;
          message.error(msg || "网络不稳定，请刷新重试");
          return Promise.reject(res.data);
        }
      },
      error => {
        const msg = error.message;
        // 关闭loading
        if (msg !== "取消请求") message.error(msg || "网络不稳定，请刷新重试");
        //取消延时loading的加载
        clearTimeout(timer);
        // 关闭loading
        this.loadingInstance && this.loadingInstance.close();
        return Promise.reject(error);
      }
    );
  }
  mergeOptions(options) {
    // 合并选项
    return { baseURL: this.baseURL, timeout: this.timeout, ...options };
  }
  request = options => {
    const instance = axios.create(); // 创建axios实例
    this.setInterceptors(instance, options); // 创建单独的拦截器
    const opts = this.mergeOptions(options); // 合并选项
    return instance(opts); // 单独拦截器的配置项
  };
  get = (url, config) => {
    // get请求 以字符串的形式传入 路径参数  ?a=1
    return this.request({
      method: "get",
      url,
      ...config // 参数可以直接展开
    });
  };
  post = (url, data, options) => {
    // post请求 数据在请求体中 {}
    return this.request({
      method: "post",
      url,
      data: data, // post要求必须传入data属性
      ...options
    });
  };
}

//oss上传
const uploadFile = (info, config = {}) => {
  const uploadAttachment = [
    "application/word",
    "application/excel",
    "application/ppt",
    "application/pdf",
    "image/jpg",
    "image/jpeg",
    "image/png"
  ];
  const uploadCover = ["image/jpg", "image/jpeg", "image/png"];
  let type = info.file.type;
  let { validateType } = config;
  //文件类型效验
  if (validateType && validateType === "attachment") {
    if (!uploadAttachment.includes(type)) {
      message.warning("不支持上传该类型文件");
      return Promise.reject();
    }
  }
  if (validateType && validateType === "cover") {
    if (!uploadCover.includes(type)) {
      message.warning("不支持上传该类型图片");
      return Promise.reject();
    }
  }
  return http
    .request({
      url: "manager/info/oss/token",
      method: "get",
      ...config
    })
    .then(res => {
      let time = Date.now()
      const name = time + '_' + info.file.name;
      const formData = new FormData();
      const key = res.data.dir + '/'+ time + "_" + "${filename}";
      formData.append("policy", res.data.policy);
      formData.append("OSSAccessKeyId", res.data.accessId);
      formData.append("success_action_status", "200");
      formData.append("signature", res.data.signature);
      formData.append("key", key);
      formData.append("file", info.file);
      formData.append("name", name);

      let basrUrl = process.env.NODE_ENV === "development" ? "oss" : "/";
      return http
        .request({
          url: res.data.host,
          method: "post",
          baseURL: basrUrl,
          headers: {
            "Content-Type": "multipart/form-data"
          },
          ...config,
          data: formData
        })
        .then(() => {
          return {
            url: res.data.host + res.data.dir + "/" + name,
            name: info.file.name
          };
        });
    });
};
const http = new HttpRequest();
export default {
  install(Vue) {
    Vue.mixin({
      data() {
        return {
          cancelRequest: []
        };
      },
      destroyed() {
        // 组件销毁，取消请求
        this.$data.cancelRequest.forEach(v => v.cancel("取消请求"));
      }
    });
    Vue.prototype.$axios = http.request;
    Vue.prototype.$get = http.get;
    Vue.prototype.$post = http.post;
    Vue.prototype.$uploadFile = uploadFile;
  },
  request: http.request
};
